`timescale 1ns / 1ps
`include "InstrHeader.h"
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2019/07/02 14:01:11
// Design Name: 
// Module Name: StallCtrlUnit
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module StallCtrlUnit(
    input   [`InstrBusWidth]	InstrBus,
    input   [4:0] Rs,
    input   [4:0] Rt,
    input   [3:0]   D_T,
    input           D_WriteRegEnable,
    input   [4:0]   D_RegId,
    input   [3:0]   E_T,
    input           E_WriteRegEnable,
    input   [4:0]   E_RegId,
	input	XALU_Busy,
	input	D_MultCalFamily,
    output  stall,
    output  [3:0]   T
    );
	assign	{`InstrBusWireSet}	=	InstrBus;
    ///////////////////////////////////////////////////////////
    wire NeedRs=(addi||addiu||add||addu||sub||subu||lw||sw||lb||lbu||lh||lhu||sb||sh||jr||jalr||mult||multu||div||divu||mthi||mtlo||
				   sllv||srlv||srav||And||Or||Xor||Nor||ori||Andi||Xori||slt||sltu||slti||sltiu||
				   beq||bne||blez||bgtz||bltz||bgez);
	wire NeedRt=(add||addu||sub||subu||sw||sb||sh||mult||multu||div||divu||sll||srl||sra||sllv||srlv||srav||
				   And||Or||Xor||Nor||slt||sltu||beq||bne||mtc0);

    wire [3:0] T_Rs=(beq||bne||blez||bgtz||bltz||bgez)																			?	0:
				(addi||addiu||add||addu||sub||subu||lw||sw||lb||lbu||lh||lhu||sb||sh||mult||multu||div||mthi||mtlo||
				divu||sllv||srlv||srav||And||Or||Xor||Nor||ori||Andi||Xori||slt||sltu||slti||sltiu)							?	1:
																																0;
																														
	wire [3:0] T_Rt=(beq||bne)																							?	0:
				(add||addu||sub||subu||mult||multu||div||divu||sll||srl||sra||sllv||srlv||srav||
				And||Or||Xor||Nor||slt||sltu)																		?	1:
				(sw||sb||sh||mtc0)																					?	2:
																														0;
																														
	wire [3:0] Tnew=(lw||lhu||lh||lbu||lb||mfc0)																?	3:
				(addi||addiu||add||addu||sub||subu||lui||jal||jalr||mfhi||mflo||sll||srl||sra||sllv||srlv||srav||
				And||Or||Xor||Nor||ori||Andi||Xori||slt||sltu||slti||sltiu)										?	2:
																													3;
    assign T = Tnew;
	wire MultFamily = (mult|multu|div|divu|mfhi|mflo|mthi|mtlo);
    /////////////////////////////////////////////////////////////
    wire    stall_Rs = NeedRs && Rs!=5'b0 &&( (D_WriteRegEnable && D_T>T_Rs && D_RegId==Rs)|| (E_WriteRegEnable && E_T>T_Rs && E_RegId==Rs)),
            stall_Rt = NeedRt && Rt!=5'b0 &&( (D_WriteRegEnable && D_T>T_Rt && D_RegId==Rt)|| (E_WriteRegEnable && E_T>T_Rt && E_RegId==Rt));
    
	wire	stall_XALU = ((XALU_Busy&MultFamily)|(MultFamily&D_MultCalFamily));
    assign	stall  = (stall_Rs||stall_Rt|stall_XALU);

endmodule
